//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//    NotificationConditionHelperTest.cs
//
// Abstract:
//    
//    Unit tests for generation of rule condition descriptions.
//
// Classes:
//
//    Microsoft.EnhancedReminders.OutlookAddIn.UnitTests.NotificationConditionHelperTest
//
//--

using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
using Microsoft.OfficeCommunicationsServer.Applications.Common;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.EnhancedReminders.OutlookAddIn.UnitTests
{   
    /// <summary>
    ///This is a test class for NotificationConditionHelper.
    ///</summary>
    [TestClass()]
    public class NotificationConditionHelperTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        /// Verify a time condition description.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestTimeConditionDescription1()
        {
            // Create descriptor for 2:30 AM - 6:00 AM on Sunday.
            NotificationTimeCondition time = new NotificationTimeCondition();
            time.TimeArray[5] = true;
            time.TimeArray[6] = true;
            time.TimeArray[7] = true;
            time.TimeArray[8] = true;
            time.TimeArray[9] = true;
            time.TimeArray[10] = true;
            time.TimeArray[11] = true;

            string description = NotificationConditionHelper_Accessor.GenerateTimeConditionDescription(time);

            string expected = "after 2:30 AM and before 6:00 AM on Sunday";

            Assert.AreEqual(expected, description, "description");
        }

        /// <summary>
        /// Verify a time condition which spans multiple days.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestTimeConditionDescription2()
        {
            NotificationTimeCondition time = new NotificationTimeCondition();
            for (int i = 84; i < 117; i++) // From 6:00pm Monday -> 10:30am Tuesday.
            {
                time.TimeArray[i] = true;
            }
            
            string description = NotificationConditionHelper_Accessor.GenerateTimeConditionDescription(time);

            string expected = "after 6:00 PM on Monday and before 10:30 AM on Tuesday";

            Assert.AreEqual(expected, description, "description");
        }

        /// <summary>
        /// Verify setting only the final bit in the time array.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestTimeConditionDescription3()
        {
            NotificationTimeCondition time = new NotificationTimeCondition();
            time.TimeArray[time.TimeArray.Length - 1] = true;

            string description = NotificationConditionHelper_Accessor.GenerateTimeConditionDescription(time);

            string expected = "after 11:30 PM on Saturday and before 12:00 AM on Sunday";

            Assert.AreEqual(expected, description, "description");
        }

        
        /// <summary>
        /// Verify people condition description.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestPeopleConditionDescription()
        {
            NotificationPeopleCondition people = new NotificationPeopleCondition();
            people.Contacts.Add(new ContactInfo(null, "123", "John Smith"));
            people.Contacts.Add(new ContactInfo(null, "456", "Jane Jones"));

            string description = NotificationConditionHelper_Accessor.GeneratePeopleConditionDescription(people);

            string expected = Properties.Resources.RulesDialogPeopleFrom + "John Smith" +
                Properties.Resources.RulesDialogDescriptionSeparator + "Jane Jones";

            Assert.AreEqual(expected, description, "description");
        }

        /// <summary>
        /// Verify default status condition description.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestStatusConditionDescription1()
        {
            NotificationStatusCondition status = new NotificationStatusCondition();
            status.Presence = PresenceStates.Away;

            string description = NotificationConditionHelper_Accessor.GenerateStatusConditionDescription(status);

            string expected = Properties.Resources.RulesDialogStatusPrefix + "\"" + 
                Properties.Resources.PresenceStateAway + "\"";

            Assert.AreEqual(expected, description, "description");
        }

        /// <summary>
        /// Verify default status condition description.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestStatusConditionDescription2()
        {
            NotificationStatusCondition status = new NotificationStatusCondition();
            status.Presence = PresenceStates.Away | PresenceStates.BeRightBack | PresenceStates.IdleOnline | PresenceStates.IdleBusy | PresenceStates.Offline;

            string description = NotificationConditionHelper_Accessor.GenerateStatusConditionDescription(status);

            string expected = Properties.Resources.RulesDialogStatusPrefix +
                "\"" + Properties.Resources.PresenceStateBeRightBack + "\"" +
                Properties.Resources.RulesDialogDescriptionSeparator +
                "\"" + Properties.Resources.PresenceStateAway + "\"" +
                Properties.Resources.RulesDialogDescriptionSeparator +
                "\"" + Properties.Resources.PresenceStateIdleOnline + "\"" +
                Properties.Resources.RulesDialogDescriptionSeparator +
                "\"" + Properties.Resources.PresenceStateIdleBusy + "\"" +
                Properties.Resources.RulesDialogDescriptionSeparator +
                "\"" + Properties.Resources.PresenceStateOffline + "\"";

            Assert.AreEqual(expected, description, "description");
        }

        /// <summary>
        /// Verify description string is generated correcly for multiple conditions.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestMultipleConditionDescription()
        {
            NotificationRuleItem rule = new NotificationRuleItem(MailboxType.Voicemail, "test", DateTime.Now, null);

            // Create conditions.
            NotificationTimeCondition time = Helpers.AssertCast<NotificationTimeCondition>(rule.Conditions[0]);
            time.TimeArray[0] = true;
            NotificationPeopleCondition people = Helpers.AssertCast<NotificationPeopleCondition>(rule.Conditions[1]);
            people.Contacts.Add(new ContactInfo(null, "id", "John Smith"));
            NotificationStatusCondition status = Helpers.AssertCast<NotificationStatusCondition>(rule.Conditions[2]);
            status.Presence = PresenceStates.Away;

            // Verify time + people conditions selected.
            time.IsSelected = true;
            people.IsSelected = true;
            status.IsSelected = false;
            Assert.AreEqual("after 12:00 AM and before 12:30 AM on Sunday and from John Smith",
                            NotificationConditionHelper_Accessor.GenerateConditionDescription(rule, 1000),
                            "time and people conditions");

            // Verify time + status conditions selected.
            time.IsSelected = true;
            people.IsSelected = false;
            status.IsSelected = true;
            Assert.AreEqual("after 12:00 AM and before 12:30 AM on Sunday and while my status is \"Away\"",
                            NotificationConditionHelper_Accessor.GenerateConditionDescription(rule, 1000),
                            "time and status conditions");

            // Verify people + status conditions selected.
            time.IsSelected = false;
            people.IsSelected = true;
            status.IsSelected = true;
            Assert.AreEqual("from John Smith and while my status is \"Away\"",
                            NotificationConditionHelper_Accessor.GenerateConditionDescription(rule, 1000),
                            "people and status conditions");

            // Verify time + people + status conditions selected. 
            time.IsSelected = true;
            people.IsSelected = true;
            status.IsSelected = true;
            Assert.AreEqual("after 12:00 AM and before 12:30 AM on Sunday and from John Smith and while my status is \"Away\"",
                            NotificationConditionHelper_Accessor.GenerateConditionDescription(rule, 1000),
                            "time, people and status conditions");
        }

        /// <summary>
        /// Test generating the action string for a voicemail rule with an empty channel list.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionEmptyVoicemailChannels()
        {
            string description = NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.Voicemail,
                new NotificationChannelListAbsoluteTime(new List<NotificationChannel>()),
                new NotificationChannelListLeadTime(new List<NotificationChannel>()),
                1000);
            
            Assert.AreEqual(Properties.Resources.RulesDialogActionInvalid, description);
        }

        /// <summary>
        /// Test generating the action string for a voicemail rule with one channel enabled.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionVoicemail1()
        {
            NotificationChannelListAbsoluteTime notificationChannels = null;
            NotificationChannelListLeadTime joinNowChannels = null;
            CreateChannels(out notificationChannels, out joinNowChannels);

            notificationChannels.Channels[0].IsEnabled = true;

            string description = 
                NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.Voicemail, notificationChannels , joinNowChannels, 10000);

            string expected = Properties.Resources.RulesDialogActionSendIM + " \"" + notificationChannels.Channels[0].UserDefinedName + '\"';

            Assert.AreEqual(expected, description);
        }

        /// <summary>
        /// Test generating the "action" string for a voicemail rule with multiple channels enabled.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionVoicemail2()
        {
            NotificationChannelListAbsoluteTime notificationChannels = null;
            NotificationChannelListLeadTime joinNowChannels = null;
            CreateChannels(out notificationChannels, out joinNowChannels);

            notificationChannels.Channels[0].IsEnabled = true;
            notificationChannels.Channels[1].IsEnabled = true;

            string description = 
                NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.Voicemail, notificationChannels, joinNowChannels, 10000);

            string expected = Properties.Resources.RulesDialogActionSendIM + " \"" + notificationChannels.Channels[0].UserDefinedName + '\"' +
                Properties.Resources.RulesDialogActionThen + Properties.Resources.RulesDialogActionCall + " \"" + notificationChannels.Channels[1].UserDefinedName + '\"';

            Assert.AreEqual(expected, description);
        }

        /// <summary>
        /// Test generating the action string for a calendar rule with no channels enabled.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionInvalidCalendarChannels1()
        {
            string description = NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.CalendarItem,
                new NotificationChannelListAbsoluteTime(new List<NotificationChannel>()),
                new NotificationChannelListLeadTime(new List<NotificationChannel>()),
                1000);

            Assert.AreEqual(Properties.Resources.RulesDialogActionInvalid, description);
        }

        /// <summary>
        /// Test generating the action string for a calendar rule with a notification channel enabled but no absolute 
        /// time selected.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionInvalidCalendarChannels2()
        {
            NotificationChannelListAbsoluteTime notificationChannels = null;
            NotificationChannelListLeadTime joinNowChannels = null;
            CreateChannels(out notificationChannels, out joinNowChannels);
            notificationChannels.Channels[0].IsEnabled = true;

            string description = NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.CalendarItem,
                notificationChannels,
                joinNowChannels,
                1000);

            Assert.AreEqual(Properties.Resources.RulesDialogActionInvalid, description);
        }

        /// <summary>
        /// Test generating the action string for a calendar rule with a join now channel enabled but no lead 
        /// time selected.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionInvalidJoinNowChannels()
        {
            NotificationChannelListAbsoluteTime notificationChannels = null;
            NotificationChannelListLeadTime joinNowChannels = null;
            CreateChannels(out notificationChannels, out joinNowChannels);
            joinNowChannels.Channels[0].IsEnabled = true;

            string description = NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.CalendarItem,
                notificationChannels,
                joinNowChannels,                
                1000);

            Assert.AreEqual(Properties.Resources.RulesDialogActionInvalid, description);
        }

        /// <summary>
        /// Test generating the action string for a calendar rule with one enabled channel and absolute time selected.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionSingleCalendarChannel()
        {
            NotificationChannelListAbsoluteTime notificationChannels = null;
            NotificationChannelListLeadTime joinNowChannels = null;
            CreateChannels(out notificationChannels, out joinNowChannels);
            
            notificationChannels.Channels[0].IsEnabled = true;
            notificationChannels.AbsoluteTime = new DateTime(2008, 1, 1, 3, 45, 0);

            string description = NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.CalendarItem,
                notificationChannels,
                joinNowChannels,
                1000);

            string expected = Properties.Resources.RulesDialogActionCalendarPrefix +
                NotificationConditionHelper_Accessor.GetLocalizedDateTimeString(notificationChannels.AbsoluteTime) + ' ' +
                Properties.Resources.RulesDialogActionSendIM + " \"" +
                notificationChannels.Channels[0].UserDefinedName + '\"';

            Assert.AreEqual(expected, description);
        }

        /// <summary>
        /// Test generating the action string for a calendar rule with multiple notification channels enabled but 
        /// no absolute time selected.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionMultipleCalendarChannel()
        {
            NotificationChannelListAbsoluteTime notificationChannels = null;
            NotificationChannelListLeadTime joinNowChannels = null;
            CreateChannels(out notificationChannels, out joinNowChannels);

            notificationChannels.Channels[1].IsEnabled = true;
            notificationChannels.Channels[2].IsEnabled = true;
            notificationChannels.AbsoluteTime = new DateTime(2008, 1, 1, 3, 45, 0);

            string description = NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.CalendarItem,
                notificationChannels,
                joinNowChannels,
                1000);

            string expected = Properties.Resources.RulesDialogActionCalendarPrefix +
                NotificationConditionHelper_Accessor.GetLocalizedDateTimeString(notificationChannels.AbsoluteTime) + ' ' +
                Properties.Resources.RulesDialogActionCall + " \"" +
                notificationChannels.Channels[1].UserDefinedName + '\"' +
                Properties.Resources.RulesDialogActionThen +
                Properties.Resources.RulesDialogActionSendSms + " \"" +
                notificationChannels.Channels[2].UserDefinedName + '\"';

            Assert.AreEqual(expected, description);
        }

        /// <summary>
        /// Test generating the action string for a calendar rule with a join now channel enabled.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionSingleJoinNowChannel()
        {
            NotificationChannelListAbsoluteTime notificationChannels = null;
            NotificationChannelListLeadTime joinNowChannels = null;
            CreateChannels(out notificationChannels, out joinNowChannels);

            joinNowChannels.Channels[0].IsEnabled = true;
            joinNowChannels.LeadTime = 20;

            string description = NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.CalendarItem,
                notificationChannels,
                joinNowChannels,
                1000);

            string expected = Properties.Resources.RulesDialogActionAutoJoinPrefix + "\"" +
                joinNowChannels.Channels[0].UserDefinedName + '\"';

            Assert.AreEqual(expected, description);

        }

        /// <summary>
        /// Test generating the action string for a calendar item with both notification and join now channels enabled.
        ///</summary>
        [TestMethod()]
        [DeploymentItem("Microsoft.EnhancedReminders.OutlookAddIn.dll")]
        public void TestActionDescriptionCalendarAndJoinNowChannels()
        {
            NotificationChannelListAbsoluteTime notificationChannels = null;
            NotificationChannelListLeadTime joinNowChannels = null;
            CreateChannels(out notificationChannels, out joinNowChannels);

            notificationChannels.Channels[0].IsEnabled = true;
            notificationChannels.AbsoluteTime = new DateTime(2008, 1, 1, 14, 45, 0);
            joinNowChannels.Channels[0].IsEnabled = true;
            joinNowChannels.LeadTime = 20;

            string description = NotificationConditionHelper_Accessor.GenerateActionDescription(MailboxType.CalendarItem,
                notificationChannels,
                joinNowChannels,
                1000);

            string expected = Properties.Resources.RulesDialogActionCalendarPrefix +
                NotificationConditionHelper_Accessor.GetLocalizedDateTimeString(notificationChannels.AbsoluteTime) + ' ' +
                Properties.Resources.RulesDialogActionSendIM + " \"" +
                notificationChannels.Channels[0].UserDefinedName + '\"' +
                Properties.Resources.RulesDialogAnd +
                Properties.Resources.RulesDialogActionAutoJoinPrefix + "\"" +
                joinNowChannels.Channels[0].UserDefinedName + '\"';

            Assert.AreEqual(expected, description);
        }

        /// <summary>
        /// Helper method to create a default list of notification and join now channels.  Both channel lists will 
        /// have "IsEnabled" set to false.
        /// </summary>
        /// <param name="notificationChannels">The returned notification channel list.</param>
        /// <param name="joinNowChannels">The returned join now channel list.</param>
        private static void CreateChannels(out NotificationChannelListAbsoluteTime notificationChannels, out NotificationChannelListLeadTime joinNowChannels)
        {
            List<NotificationChannel> channels = new List<NotificationChannel>();
            channels.Add(new NotificationChannel(NotificationChannelType.Communicator, "Communicator", "foo@bar.com"));
            channels.Add(new NotificationChannel(NotificationChannelType.Phone, "Mobile Phone", "1234"));
            channels.Add(new NotificationCustomChannel(NotificationChannelType.SMS, "Custom", "1234@foo.bar.com"));
            foreach (NotificationChannel channel in channels)
            {
                channel.IsEnabled = false;
            }

            notificationChannels = new NotificationChannelListAbsoluteTime(channels);

            Assert.IsFalse(notificationChannels.IsEnabled, "notificationChannels.IsEnabled");

            channels.RemoveAt(2); // Remove the SMS channel for join now
            channels.Reverse(); // Change the order to 
            joinNowChannels = new NotificationChannelListLeadTime(channels);

            Assert.IsFalse(joinNowChannels.IsEnabled, "joinNowChannels.IsEnabled");
        }
    }
}
